package com.pick.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pick.admin.entity.SysMenu;
import com.pick.admin.mapper.SysMenuMapper;
import com.pick.admin.service.SysMenuService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 系统菜单服务实现类
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Override
    public List<SysMenu> getMenuTree() {
        List<SysMenu> allMenus = this.list(new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getStatus, 1)
                .orderByAsc(SysMenu::getSortOrder));
        
        return buildMenuTree(allMenus, 0L);
    }

    @Override
    public boolean createMenu(SysMenu menu) {
        // 设置默认值
        if (menu.getStatus() == null) {
            menu.setStatus(1); // 默认启用
        }
        if (menu.getParentId() == null) {
            menu.setParentId(0L); // 默认为根菜单
        }
        if (menu.getMenuType() == null) {
            menu.setMenuType(2); // 默认为菜单类型
        }
        if (menu.getVisible() == null) {
            menu.setVisible(1); // 默认可见
        }
        if (menu.getIsFrame() == null) {
            menu.setIsFrame(0); // 默认非外链
        }
        if (menu.getIsCache() == null) {
            menu.setIsCache(0); // 默认不缓存
        }
        
        // 自动生成权限标识
        if (menu.getPermission() == null || menu.getPermission().trim().isEmpty()) {
            if (menu.getMenuPath() != null && !menu.getMenuPath().trim().isEmpty()) {
                String path = menu.getMenuPath().replaceAll("/", ":");
                if (path.startsWith(":")) {
                    path = path.substring(1);
                }
                menu.setPermission(path + ":list");
            }
        }
        
        return this.save(menu);
    }

    @Override
    public boolean updateMenu(SysMenu menu) {
        return this.updateById(menu);
    }

    @Override
    @Transactional
    public boolean deleteMenu(Long menuId) {
        // 检查是否有子菜单
        long childCount = this.count(new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getParentId, menuId));
        if (childCount > 0) {
            throw new RuntimeException("该菜单下还有子菜单，无法删除");
        }
        
        // 删除菜单
        return this.removeById(menuId);
    }

    @Override
    public List<SysMenu> getMenuTreeByUserId(Long userId) {
        List<SysMenu> userMenus = baseMapper.selectMenusByUserId(userId);
        return buildMenuTree(userMenus, 0L);
    }

    /**
     * 构建菜单树
     */
    private List<SysMenu> buildMenuTree(List<SysMenu> allMenus, Long parentId) {
        List<SysMenu> result = new ArrayList<>();
        
        for (SysMenu menu : allMenus) {
            if (parentId.equals(menu.getParentId())) {
                List<SysMenu> children = buildMenuTree(allMenus, menu.getId());
                menu.setChildren(children.isEmpty() ? null : children);
                result.add(menu);
            }
        }
        
        // 按排序号排序
        result.sort((m1, m2) -> {
            Integer sort1 = m1.getSortOrder() != null ? m1.getSortOrder() : 0;
            Integer sort2 = m2.getSortOrder() != null ? m2.getSortOrder() : 0;
            return sort1.compareTo(sort2);
        });
        
        return result;
    }
    
    /**
     * 检查菜单名称是否重复
     */
    @Override
    public boolean isMenuNameExists(String menuName, Long parentId, Long excludeId) {
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysMenu::getMenuName, menuName)
               .eq(SysMenu::getParentId, parentId);
        if (excludeId != null) {
            wrapper.ne(SysMenu::getId, excludeId);
        }
        return this.count(wrapper) > 0;
    }
    
    /**
     * 检查菜单路径是否重复
     */
    @Override
    public boolean isMenuPathExists(String menuPath, Long excludeId) {
        if (menuPath == null || menuPath.trim().isEmpty()) {
            return false;
        }
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysMenu::getMenuPath, menuPath);
        if (excludeId != null) {
            wrapper.ne(SysMenu::getId, excludeId);
        }
        return this.count(wrapper) > 0;
    }
}